package com.sdkj.seckill.rocketmqTest.batchMessage;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @Description 消息列表分割
 * @Author Jiang
 * @Date 2022/01/19 19:44
 * @Version 1.0.0
 */

public class ListSplitter implements Iterator<List<Message>> {

    private final int SIZE_LIMIT = 1024 * 1024 * 4;
    private final List<Message> messages;
    private int currIndex;

    public ListSplitter(List<Message> messages) {
        this.messages = messages;
    }


    @Override
    public boolean hasNext() {
        return currIndex < messages.size();
    }

    /**
     * 返回分割后的一个限定大小范围内批量消息
     * @return
     */
    @Override
    public List<Message> next() {
        int startIndex = getStartIndex();
        int nextIndex = startIndex;
        int totalSize = 0;
        for (; nextIndex < messages.size(); nextIndex++) {
            Message message = messages.get(nextIndex);
            int tmpSize = calcMessageSize(message);
            if (tmpSize + totalSize > SIZE_LIMIT) {
                break;
            } else {
                totalSize += tmpSize;
            }
        }
        List<Message> subList = messages.subList(startIndex, nextIndex);
        currIndex = nextIndex;
        return subList;
    }

    /**
     * 计算批量消息文件的大小
     *
     * @param message
     * @return
     */
    private int calcMessageSize(Message message) {
        int tmpSize = message.getTopic().length() + message.getBody().length;
        Map<String, String> properties = message.getProperties();
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            tmpSize += entry.getKey().length() + entry.getValue().length();
        }

        tmpSize = tmpSize + 20;//增加日志的开销20字节;
        return tmpSize;
    }

    /**
     * 获得批量消息的头部索引
     * @return
     */
    private int getStartIndex() {
        Message currentMessage = messages.get(currIndex);
        int tmpSize = calcMessageSize(currentMessage);
        while (tmpSize > SIZE_LIMIT) {
            currIndex += 1;
            Message message = messages.get(currIndex);
            tmpSize = calcMessageSize(message);
        }
        return tmpSize;
    }

    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("BatchExample");
        producer.setNamesrvAddr("47.98.172.125:9876");
        List<Message> messages = new ArrayList<Message>();
        //把大的消息分裂成若干个小的消息
        ListSplitter splitSplitter = new ListSplitter(messages);
        while (splitSplitter.hasNext()) {
            List<Message> listItems = splitSplitter.next();
            producer.send(listItems);
        }
    }
}
